package org.iabako.server.servlet;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;
import org.iabako.server.serviceimpl.security.SessionUser;
import org.iabako.shared.iservice.user.UserService;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Created by jose on 15/12/14.
 */
public class PaymentSuccessServlet extends HttpServlet {

    static Logger log = Logger.getLogger(PaymentSuccessServlet.class.getName());

    private final String PATH_TO_PROPERTIES = "/WEB-INF/classes/org/iabako/conf/iabako.properties";
    private final String URL_PAYPAL_TX_VERIFICATION_PROPERTY = "paypal_transaction_verification_url";
    private final String PAYPAL_TRANSACTION_TOKEN = "paypal_transaction_token";
    private final String URL_PAYMENT_FAIL_PROPERTY = "url_payment_fail";
    private final String URL_PAYMENT_ERROR_PROPERTY = "url_payment_error";
    private final String URL_PAYMENT_SUCCESS_PROPERTY = "url_payment_success";

    @Autowired
    SessionUser sessionUser;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        log.info("Payment verification...");

        //It comes back from PayPal
        if (sessionUser != null && sessionUser.getUser() != null) {
            sessionUser.getUser().setGoToPayPal(false);
        }

        Properties prop = new Properties();
        prop.load(getServletContext().getResourceAsStream(PATH_TO_PROPERTIES));

        try {

            String paypalTransactionId = request.getParameter("tx");

            if (GenericTools.isEmpty(paypalTransactionId)) {
                log.error("Payment verification FAIL : No tx parameter found");
                response.sendRedirect(prop.getProperty(URL_PAYMENT_FAIL_PROPERTY));
                return;
            }

            String url = prop.getProperty(URL_PAYPAL_TX_VERIFICATION_PROPERTY);

            HttpClient client = HttpClientBuilder.create().build();
            HttpPost post = new HttpPost(url);
            List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
            urlParameters.add(new BasicNameValuePair("cmd", "_notify-synch"));
            urlParameters.add(new BasicNameValuePair("tx", paypalTransactionId));
            urlParameters.add(new BasicNameValuePair("at", prop.getProperty(PAYPAL_TRANSACTION_TOKEN)));
            urlParameters.add(new BasicNameValuePair("submit", "PDT"));

            /* Test example :
            HttpPost post = new HttpPost("https://www.sandbox.paypal.com/cgi-bin/webscr");
            List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
            urlParameters.add(new BasicNameValuePair("cmd", "_notify-synch"));
            urlParameters.add(new BasicNameValuePair("tx", paypalTransactionId));
            urlParameters.add(new BasicNameValuePair("at", "p0wwIIaN8cBhebjsWPqui8C8dQRnayVbQzzeLw4GzJvAxugVeNL4ReUenfu"));
            urlParameters.add(new BasicNameValuePair("submit", "PDT"));*/

            post.setEntity(new UrlEncodedFormEntity(urlParameters));

            log.info("Calling PayPal service...");
            HttpResponse postResponse = client.execute(post);

            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(postResponse.getEntity().getContent()));

            StringBuilder result = new StringBuilder();
            String line = "";

            String iabakoTxId = null;
            String paymentStatus = null;
            String payerEmail = null;

            while ((line = rd.readLine()) != null) {
                result.append(line);
                result.append("\n");
                if (line.contains("invoice=")) {
                    iabakoTxId = line.substring(line.indexOf("invoice=") + "invoice=".length());
                }
                if (line.contains("payment_status=")) {
                    paymentStatus = line.substring(line.indexOf("payment_status=") + "payment_status=".length());
                }
                if (line.contains("payer_email=")) {
                    payerEmail = line.substring(line.indexOf("payer_email=") + "payer_email=".length());
                    payerEmail = URLDecoder.decode(payerEmail, "UTF-8");
                }
            }

            String payPalResponse = URLDecoder.decode(result.toString(), "UTF-8");

            if (payPalResponse.contains("SUCCESS")
                    && !payPalResponse.contains("FAIL")
                    && iabakoTxId != null && paymentStatus != null && payerEmail != null) {

                log.info("Payment verification SUCCESS");

                //business task to take into account user payment
                UserService userService = (UserService) getServletContext().getAttribute("userService");

                if (paymentStatus.trim().equalsIgnoreCase("Completed")) {
                    userService.setUserPayPalTokenPayed(iabakoTxId, payerEmail, payPalResponse);
                } else {
                    userService.setUserPayPalTokenToVerify(iabakoTxId, payPalResponse);
                }

                //Redirection to IABAKO UI with iabakoTxId as URL param
                response.sendRedirect(prop.getProperty(URL_PAYMENT_SUCCESS_PROPERTY) + "@" + iabakoTxId);
                return;
            }

            log.error("Payment verification FAIL : Paypal FAIL response");
            log.error(payPalResponse);
            response.sendRedirect(prop.getProperty(URL_PAYMENT_FAIL_PROPERTY));
            return;

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            //All exceptions must be catch
            response.sendRedirect(prop.getProperty(URL_PAYMENT_ERROR_PROPERTY));
            return;
        }
    }
}
